home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / vidhrdw / gyruss.c < prev    next >
C/C++ Source or Header  |  2000-04-04  |  12KB  |  475 lines

  1. /***************************************************************************
  2.  
  3.   vidhrdw.c
  4.  
  5.   Functions to emulate the video hardware of the machine.
  6.  
  7. ***************************************************************************/
  8.  
  9. #include "driver.h"
  10. #include "vidhrdw/generic.h"
  11.  
  12.  
  13.  
  14. unsigned char *gyruss_spritebank,*gyruss_6809_drawplanet,*gyruss_6809_drawship;
  15. static int flipscreen;
  16.  
  17.  
  18. typedef struct {
  19.   unsigned char y;
  20.   unsigned char shape;
  21.   unsigned char attr;
  22.   unsigned char x;
  23. } Sprites;
  24.  
  25.  
  26.  
  27. /***************************************************************************
  28.  
  29.   Convert the color PROMs into a more useable format.
  30.  
  31.   Gyruss has one 32x8 palette PROM and two 256x4 lookup table PROMs
  32.   (one for characters, one for sprites).
  33.   The palette PROM is connected to the RGB output this way:
  34.  
  35.   bit 7 -- 220 ohm resistor  -- BLUE
  36.         -- 470 ohm resistor  -- BLUE
  37.         -- 220 ohm resistor  -- GREEN
  38.         -- 470 ohm resistor  -- GREEN
  39.         -- 1  kohm resistor  -- GREEN
  40.         -- 220 ohm resistor  -- RED
  41.         -- 470 ohm resistor  -- RED
  42.   bit 0 -- 1  kohm resistor  -- RED
  43.  
  44. ***************************************************************************/
  45. void gyruss_vh_convert_color_prom(unsigned char *palette, unsigned short *colortable,const unsigned char *color_prom)
  46. {
  47.     int i;
  48.     #define TOTAL_COLORS(gfxn) (Machine->gfx[gfxn]->total_colors * Machine->gfx[gfxn]->color_granularity)
  49.     #define COLOR(gfxn,offs) (colortable[Machine->drv->gfxdecodeinfo[gfxn].color_codes_start + offs])
  50.  
  51.  
  52.     for (i = 0;i < Machine->drv->total_colors;i++)
  53.     {
  54.         int bit0,bit1,bit2;
  55.  
  56.  
  57.         /* red component */
  58.         bit0 = (*color_prom >> 0) & 0x01;
  59.         bit1 = (*color_prom >> 1) & 0x01;
  60.         bit2 = (*color_prom >> 2) & 0x01;
  61.         *(palette++) = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
  62.         /* green component */
  63.         bit0 = (*color_prom >> 3) & 0x01;
  64.         bit1 = (*color_prom >> 4) & 0x01;
  65.         bit2 = (*color_prom >> 5) & 0x01;
  66.         *(palette++) = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
  67.         /* blue component */
  68.         bit0 = 0;
  69.         bit1 = (*color_prom >> 6) & 0x01;
  70.         bit2 = (*color_prom >> 7) & 0x01;
  71.         *(palette++) = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
  72.  
  73.         color_prom++;
  74.     }
  75.  
  76.     /* color_prom now points to the beginning of the sprite lookup table */
  77.  
  78.     /* sprites */
  79.     for (i = 0;i < TOTAL_COLORS(1);i++)
  80.         COLOR(1,i) = *(color_prom++) & 0x0f;
  81.  
  82.     /* characters */
  83.     for (i = 0;i < TOTAL_COLORS(0);i++)
  84.         COLOR(0,i) = (*(color_prom++) & 0x0f) + 0x10;
  85. }
  86.  
  87.  
  88.  
  89. /* convert sprite coordinates from polar to cartesian */
  90. static int SprTrans(Sprites *u)
  91. {
  92. #define YTABLE_START (0xe000)
  93. #define SINTABLE_START (0xe400)
  94. #define COSTABLE_START (0xe600)
  95.     int ro;
  96.     int theta2;
  97.     unsigned char *table;
  98.  
  99.  
  100.     ro = memory_region(REGION_CPU4)[YTABLE_START + u->y];
  101.     theta2 = 2 * u->x;
  102.  
  103.     /* cosine table */
  104.     table = &memory_region(REGION_CPU4)[COSTABLE_START];
  105.  
  106.     u->y = (table[theta2+1] * ro) >> 8;
  107.     if (u->y >= 0x80)
  108.     {
  109.         u->x = 0;
  110.         return 0;
  111.     }
  112.     if (table[theta2] != 0)    /* negative */
  113.     {
  114.         if (u->y >= 0x78)    /* avoid wraparound from top to bottom of screen */
  115.         {
  116.             u->x = 0;
  117.             return 0;
  118.         }
  119.         u->y = -u->y;
  120.     }
  121.  
  122.     /* sine table */
  123.     table = &memory_region(REGION_CPU4)[SINTABLE_START];
  124.  
  125.     u->x = (table[theta2+1] * ro) >> 8;
  126.     if (u->x >= 0x80)
  127.     {
  128.         u->x = 0;
  129.         return 0;
  130.     }
  131.     if (table[theta2] != 0)    /* negative */
  132.         u->x = -u->x;
  133.  
  134.  
  135.     /* convert from logical coordinates to screen coordinates */
  136.     if (u->attr & 0x10)
  137.         u->y += 0x78;
  138.     else
  139.         u->y += 0x7C;
  140.  
  141.     u->x += 0x78;
  142.  
  143.  
  144.     return 1;    /* queue this sprite */
  145. }
  146.  
  147.  
  148.  
  149. /* this macro queues 'nq' sprites at address 'u', into queue at 'q' */
  150. #define SPR(n) ((Sprites*)&sr[4*(n)])
  151.  
  152.  
  153.  
  154.     /* Gyruss uses a semaphore system to queue sprites, and when critic
  155.        region is released, the 6809 processor writes queued sprites onto
  156.        screen visible area.
  157.        When a701 = 0 and a702 = 1 gyruss hardware queue sprites.
  158.        When a701 = 1 and a702 = 0 gyruss hardware draw sprites.
  159.  
  160.            both Z80 e 6809 are interrupted at the same time by the
  161.            VBLANK interrupt.  If there is some work to do (example
  162.            A7FF is not 0 or FF), 6809 waits for Z80 to store a 1 in
  163.            A701 and draw currently queued sprites
  164.     */
  165. WRITE_HANDLER( gyruss_queuereg_w )
  166. {
  167.     if (data == 1)
  168.     {
  169.         int n;
  170.         unsigned char *sr;
  171.  
  172.  
  173.         /* Gyruss hardware stores alternatively sprites at position
  174.            0xa000 and 0xa200.  0xA700 tells which one is used.
  175.         */
  176.  
  177.         if (*gyruss_spritebank == 0)
  178.             sr = spriteram;
  179.         else sr = spriteram_2;
  180.  
  181.  
  182.         /* #0-#3 - ship */
  183.  
  184.         /* #4-#23 */
  185.         if (*gyruss_6809_drawplanet)    /* planet is on screen */
  186.         {
  187.             SprTrans(SPR(4));    /* #4 - polar coordinates - ship */
  188.  
  189.             SPR(5)->x = 0;    /* #5 - unused */
  190.  
  191.             /* #6-#23 - planet */
  192.         }
  193.         else
  194.         {
  195.             for (n = 4;n < 24;n += 2)    /* 10 double height sprites in polar coordinates - enemies flying */
  196.             {
  197.                 SprTrans(SPR(n));
  198.  
  199.                 SPR(n+1)->x = 0;
  200.             }
  201.         }
  202.  
  203.  
  204.         /* #24-#59 */
  205.         for (n = 24;n < 60;n++)    /* 36 sprites in polar coordinates - enemies at center of screen */
  206.             SprTrans(SPR(n));
  207.  
  208.  
  209.         /* #60-#63 - unused */
  210.  
  211.  
  212.         /* #64-#77 */
  213.         if (*gyruss_6809_drawship == 0)
  214.         {
  215.             for (n = 64;n < 78;n++)    /* 14 sprites in polar coordinates - bullets */
  216.                 SprTrans(SPR(n));
  217.         }
  218.         /* else 14 sprites - player ship being formed */
  219.  
  220.  
  221.         /* #78-#93 - stars */
  222.         for (n = 78;n < 86;n++)
  223.         {
  224.             if (SprTrans(SPR(n)))
  225.             {
  226.                 /* make a mirror copy */
  227.                 SPR(n+8)->x = SPR(n)->y - 4;
  228.                 SPR(n+8)->y = SPR(n)->x + 4;
  229.             }
  230.             else
  231.                 SPR(n+8)->x = 0;
  232.         }
  233.     }
  234. }
  235.  
  236.  
  237.  
  238. WRITE_HANDLER( gyruss_flipscreen_w )
  239. {
  240.     if (flipscreen != (data & 1))
  241.     {
  242.         flipscreen = data & 1;
  243.         memset(dirtybuffer,1,videoram_size);
  244.     }
  245. }
  246.  
  247.  
  248.  
  249. /* Return the current video scan line */
  250. READ_HANDLER( gyruss_scanline_r )
  251. {
  252.     return cpu_scalebyfcount(256);
  253. }
  254.  
  255.  
  256.  
  257. /***************************************************************************
  258.  
  259.   Draw the game screen in the given osd_bitmap.
  260.   Do NOT call osd_update_display() from this function, it will be called by
  261.   the main emulation engine.
  262.  
  263. ***************************************************************************/
  264. void gyruss_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh)
  265. {
  266.     int offs;
  267.  
  268.  
  269.     /* for every character in the Video RAM, check if it has been modified */
  270.     /* since last time and update it accordingly. */
  271.     for (offs = videoram_size - 1;offs >= 0;offs--)
  272.     {
  273.         if (dirtybuffer[offs])
  274.         {
  275.             int sx,sy,flipx,flipy;
  276.  
  277.  
  278.             dirtybuffer[offs] = 0;
  279.  
  280.             sx = offs % 32;
  281.             sy = offs / 32;
  282.             flipx = colorram[offs] & 0x40;
  283.             flipy = colorram[offs] & 0x80;
  284.             if (flipscreen)
  285.             {
  286.                 sx = 31 - sx;
  287.                 sy = 31 - sy;
  288.                 flipx = !flipx;
  289.                 flipy = !flipy;
  290.             }
  291.  
  292.             drawgfx(tmpbitmap,Machine->gfx[0],
  293.                     videoram[offs] + 8 * (colorram[offs] & 0x20),
  294.                     colorram[offs] & 0x0f,
  295.                     flipx,flipy,
  296.                     8*sx,8*sy,
  297.                     &Machine->drv->visible_area,TRANSPARENCY_NONE,0);
  298.         }
  299.     }
  300.  
  301.  
  302.     /* copy the character mapped graphics */
  303.     copybitmap(bitmap,tmpbitmap,0,0,0,0,&Machine->drv->visible_area,TRANSPARENCY_NONE,0);
  304.  
  305.  
  306.     /*
  307.        offs+0 :  Ypos
  308.        offs+1 :  Sprite number
  309.        offs+2 :  Attribute in the form HF-VF-BK-DH-p3-p2-p1-p0
  310.                  where  HF is horizontal flip
  311.                         VF is vertical flip
  312.                         BK is for bank select
  313.                         DH is for double height (if set sprite is 16*16, else is 16*8)
  314.                         px is palette weight
  315.        offs+3 :  Xpos
  316.     */
  317.  
  318.     /* Draw the sprites. Note that it is important to draw them exactly in this */
  319.     /* order, to have the correct priorities. */
  320.     {
  321.         unsigned char *sr;
  322.  
  323.  
  324.         if (*gyruss_spritebank == 0)
  325.             sr = spriteram;
  326.         else sr = spriteram_2;
  327.  
  328.  
  329.         for (offs = spriteram_size - 8;offs >= 0;offs -= 8)
  330.         {
  331.             if (sr[2 + offs] & 0x10)    /* double height */
  332.             {
  333.                 if (sr[offs + 0] != 0)
  334.                     drawgfx(bitmap,Machine->gfx[3],
  335.                             sr[offs + 1]/2 + 4*(sr[offs + 2] & 0x20),
  336.                             sr[offs + 2] & 0x0f,
  337.                             !(sr[offs + 2] & 0x40),sr[offs + 2] & 0x80,
  338.                             sr[offs + 0],240-sr[offs + 3]+1,
  339.                             &Machine->drv->visible_area,TRANSPARENCY_PEN,0);
  340.             }
  341.             else    /* single height */
  342.             {
  343.                 if (sr[offs + 0] != 0)
  344.                     drawgfx(bitmap,Machine->gfx[1 + (sr[offs + 1] & 1)],
  345.                             sr[offs + 1]/2 + 4*(sr[offs + 2] & 0x20),
  346.                             sr[offs + 2] & 0x0f,
  347.                             !(sr[offs + 2] & 0x40),sr[offs + 2] & 0x80,
  348.                             sr[offs + 0],240-sr[offs + 3]+1,
  349.                             &Machine->drv->visible_area,TRANSPARENCY_PEN,0);
  350.  
  351.                 if (sr[offs + 4] != 0)
  352.                     drawgfx(bitmap,Machine->gfx[1 + (sr[offs + 5] & 1)],
  353.                             sr[offs + 5]/2 + 4*(sr[offs + 6] & 0x20),
  354.                             sr[offs + 6] & 0x0f,
  355.                             !(sr[offs + 6] & 0x40),sr[offs + 6] & 0x80,
  356.                             sr[offs + 4],240-sr[offs + 7]+1,
  357.                             &Machine->drv->visible_area,TRANSPARENCY_PEN,0);
  358.             }
  359.         }
  360.     }
  361.  
  362.  
  363.     /* redraw the characters which have priority over sprites */
  364.     for (offs = videoram_size - 1;offs >= 0;offs--)
  365.     {
  366.         int sx,sy,flipx,flipy;
  367.  
  368.  
  369.         sx = offs % 32;
  370.         sy = offs / 32;
  371.         flipx = colorram[offs] & 0x40;
  372.         flipy = colorram[offs] & 0x80;
  373.         if (flipscreen)
  374.         {
  375.             sx = 31 - sx;
  376.             sy = 31 - sy;
  377.             flipx = !flipx;
  378.             flipy = !flipy;
  379.         }
  380.  
  381.         if (colorram[offs] & 0x10)
  382.             drawgfx(bitmap,Machine->gfx[0],
  383.                     videoram[offs] + 8 * (colorram[offs] & 0x20),
  384.                     colorram[offs] & 0x0f,
  385.                     flipx,flipy,
  386.                     8*sx,8*sy,
  387.                     &Machine->drv->visible_area,TRANSPARENCY_NONE,0);
  388.     }
  389. }
  390.  
  391. void gyruss_6809_vh_screenrefresh(struct osd_bitmap *bitmap)
  392. {
  393.     int offs;
  394.  
  395.  
  396.     /* for every character in the Video RAM, check if it has been modified */
  397.     /* since last time and update it accordingly. */
  398.     for (offs = videoram_size - 1;offs >= 0;offs--)
  399.     {
  400.         if (dirtybuffer[offs])
  401.         {
  402.             int sx,sy,flipx,flipy;
  403.  
  404.  
  405.             dirtybuffer[offs] = 0;
  406.  
  407.             sx = offs % 32;
  408.             sy = offs / 32;
  409.             flipx = colorram[offs] & 0x40;
  410.             flipy = colorram[offs] & 0x80;
  411.             if (flipscreen)
  412.             {
  413.                 sx = 31 - sx;
  414.                 sy = 31 - sy;
  415.                 flipx = !flipx;
  416.                 flipy = !flipy;
  417.             }
  418.  
  419.             drawgfx(tmpbitmap,Machine->gfx[0],
  420.                     videoram[offs] + 8 * (colorram[offs] & 0x20),
  421.                     colorram[offs] & 0x0f,
  422.                     flipx,flipy,
  423.                     8*sx,8*sy,
  424.                     &Machine->drv->visible_area,TRANSPARENCY_NONE,0);
  425.         }
  426.     }
  427.  
  428.  
  429.     /* copy the character mapped graphics */
  430.     copybitmap(bitmap,tmpbitmap,0,0,0,0,&Machine->drv->visible_area,TRANSPARENCY_NONE,0);
  431.  
  432.  
  433.     /* Draw the sprites. Note that it is important to draw them exactly in this */
  434.     /* order, to have the correct priorities. */
  435.     {
  436.         for (offs = spriteram_size - 4;offs >= 0;offs -= 4)
  437.         {
  438.             drawgfx(bitmap,Machine->gfx[1 + (spriteram[offs + 1] & 1)],
  439.                     spriteram[offs + 1]/2 + 4*(spriteram[offs + 2] & 0x20),
  440.                     spriteram[offs + 2] & 0x0f,
  441.                     !(spriteram[offs + 2] & 0x40),spriteram[offs + 2] & 0x80,
  442.                     spriteram[offs],240-spriteram[offs + 3]+1,
  443.                     &Machine->drv->visible_area,TRANSPARENCY_PEN,0);
  444.         }
  445.     }
  446.  
  447.  
  448.     /* redraw the characters which have priority over sprites */
  449.     for (offs = videoram_size - 1;offs >= 0;offs--)
  450.     {
  451.         int sx,sy,flipx,flipy;
  452.  
  453.  
  454.         sx = offs % 32;
  455.         sy = offs / 32;
  456.         flipx = colorram[offs] & 0x40;
  457.         flipy = colorram[offs] & 0x80;
  458.         if (flipscreen)
  459.         {
  460.             sx = 31 - sx;
  461.             sy = 31 - sy;
  462.             flipx = !flipx;
  463.             flipy = !flipy;
  464.         }
  465.  
  466.         if ((colorram[offs] & 0x10) != 0)
  467.             drawgfx(bitmap,Machine->gfx[0],
  468.                     videoram[offs] + 8 * (colorram[offs] & 0x20),
  469.                     colorram[offs] & 0x0f,
  470.                     flipx,flipy,
  471.                     8*sx,8*sy,
  472.                     &Machine->drv->visible_area,TRANSPARENCY_NONE,0);
  473.     }
  474. }
  475.